package com.xinzhidi.web.netty.server;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xinzhidi.common.constant.AgreementConstants;
import com.xinzhidi.common.utils.HttpUtil;
import com.xinzhidi.common.utils.StringUtils;
import com.xinzhidi.common.utils.spring.SpringUtils;
import com.xinzhidi.web.dtuusr.domain.DtuUsr;
import com.xinzhidi.web.dtuusr.service.DtuUsrService;
import com.xinzhidi.web.equipment.domain.Equipment;
import com.xinzhidi.web.equipment.service.EquipmentService;
import com.xinzhidi.web.netty.entity.CommonField;
import com.xinzhidi.web.netty.entity.DeviceInstruction;
import com.xinzhidi.web.netty.service.DeviceInstructionService;
import com.xinzhidi.web.netty.service.NettyService;
import com.xinzhidi.web.netty.utils.FormatData;
import com.xinzhidi.web.netty.utils.HexadecimalUtil;
import com.xinzhidi.web.netty.utils.NettyUtils;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/***
 * @author cx
 * @date 2023/5/25 18:33
 */
@Component
public class SocketHandler extends SimpleChannelInboundHandler<byte[]> {

    private static final Logger log = LoggerFactory.getLogger(SocketHandler.class);

    public static Map<String, ChannelHandlerContext> CHANNEL_CTX_MAP = new HashMap<>();

    public static Map<ChannelHandlerContext, String> CTX_MAP = new HashMap<>();


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, byte[] sourceMsg) {
        log.info("收到源消息为:{}", sourceMsg);
        //解析注册包数据
        DtuUsrService dtuUsrService = SpringUtils.getBean(DtuUsrService.class);
        //开始----------------
        String message = bytesToHexString(sourceMsg);
        if (!message.startsWith("FE") && !message.startsWith("fe")) {
            message = hexToString(message);
            message = StringUtils.deleteWhitespace(message);
        }
        System.out.println("新的解析为：" + message);
        //结束----------------
        //判断接收到的信息是心跳包还是传送过来的数据（根据信息长度判断）
        DtuUsr dtuUsr = null;
        String channel = "";
        if (message.contains("ceebic") || message.contains("Connect")) {
            //说明是心跳包或注册包
            channel = message;
        } else {
            channel = CTX_MAP.get(ctx);
        }

        if (StringUtils.isBlank(channel)) {
            return;
        }
        CHANNEL_CTX_MAP.put(channel, ctx);
        CTX_MAP.put(ctx, channel);
        dtuUsr = this.getDtu(dtuUsrService, channel);
        if (dtuUsr == null) {
            return;
        }
        //更新dtu的最后在线时间
        dtuUsr.setStatus(0);
        dtuUsr.setUpdateTime(new Date());
        dtuUsrService.updateById(dtuUsr);

        NettyService nettyService = SpringUtils.getBean(NettyService.class);

        EquipmentService equipmentService = SpringUtils.getBean(EquipmentService.class);
        DeviceInstructionService deviceInstructionService = SpringUtils.getBean(DeviceInstructionService.class);
        CommonField commonField = NettyUtils.getCommonField(message);
//        //通过设备地址查找导入的数据，看上传信息的设备是否存在
//        boolean flag = simCardService.checkSimCard(dtuUsr.getId(), commonField.getAddressField().toUpperCase());
//        if (!flag) {
//            return;
//        }
        //已发送的指令（状态为1的）
        DeviceInstruction deviceInstruction = deviceInstructionService.getLatestDeviceInstruct(dtuUsr.getId(), commonField.getAddressField());
        LambdaQueryWrapper<Equipment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Equipment::getDtuId, dtuUsr.getId());
        wrapper.eq(Equipment::getAddress, commonField.getAddressField());
        wrapper.eq(Equipment::getDelFlag, AgreementConstants.DEL_FLAG_NO);
        Equipment equipment = equipmentService.getOne(wrapper);
        if (equipment == null) {
            if(deviceInstruction != null){
                deviceInstruction.setStatus(AgreementConstants.InstructSendingState.RETURN_EXCEPTION);
                deviceInstructionService.updateById(deviceInstruction);
            }
            return;
        }
        //修改收到的设备状态为在线
        equipment.setStatus(1);
        equipment.setUpdateTime(new Date());
        equipmentService.updateById(equipment);
        System.out.println("更新设备【" + equipment.getId() + "】状态为在线!");

        if (deviceInstruction == null) {
            deviceInstruction = deviceInstructionService.getLatestDeviceInstruct(dtuUsr.getId(), "");
            if (deviceInstruction == null) {
                return;
            }
        }
        deviceInstruction.setRecoverMessage(message);

        String address = deviceInstruction.getAddress();
        if (StringUtils.isNotBlank(address) && !address.equals(commonField.getAddressField())) {
            return;
        }

        //判断校验和是否正确，如果不正确，则直接判断对应的下发的消息为回复异常
        if (!HexadecimalUtil.getCheckCodeByAllData(message)) {
            deviceInstruction.setStatus(AgreementConstants.InstructSendingState.RETURN_EXCEPTION);
            deviceInstructionService.updateById(deviceInstruction);
            return;
        }
        deviceInstruction.setStatus(AgreementConstants.InstructSendingState.RETURN_TO_NORMAL);
        deviceInstruction.setUpdateTime(new Date());
        deviceInstructionService.updateById(deviceInstruction);
        nettyService.analyticData(message, equipment, deviceInstruction);
        ctx.writeAndFlush(sourceMsg);
    }

    /**
     * 获取dtu数据
     *
     * @param message
     * @return
     */
    private DtuUsr getDtu(DtuUsrService dtuUsrService, String message) {
        LambdaQueryWrapper<DtuUsr> wrapper = Wrappers.lambdaQuery();
        wrapper.and((w) -> {
            w.eq(DtuUsr::getUuid, message)
                    .or().eq(DtuUsr::getRegisterPackage, message);
        });
        DtuUsr dtuUsr = dtuUsrService.getOne(wrapper);
        return dtuUsr;
    }

    /**
     * 新客户端接入
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("===新客户端接入===：09909090909090：");
        log.info("新客户端接入");
//        CHANNEL_CTX_MAP.put("100001", ctx);
    }

    /**
     * 一键调控
     *
     * @param channel 通道
     * @param message 消息
     * @return 1：消息下发成功，-1：消息下发失败
     */
    public static Integer sendMessage(String channel, String message) {
//        System.out.println("需要下发的通道为：" + channel);
        ChannelHandlerContext channelHandlerContext = CHANNEL_CTX_MAP.get(channel);
        if (channelHandlerContext != null) {
            byte[] bytes = FormatData.hex2bytes(message);
            System.out.println(NettyUtils.bytes2hexFirst(bytes));
            channelHandlerContext.writeAndFlush(bytes);
            System.out.println("成功发送消息");
            return 1;
//            return "成功发送消息";
        } else {
            System.out.println("未获取到下发消息需要的通道！");
            return -1;

//            return "未获取到下发消息需要的通道！";
        }
    }

    public static void main(String[] args) {

        String host = "https://aliv8.data.moji.com";

        String method = "POST";
        String appcode = "b915a1571d8341a2aaf8ccc59c644b30";
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("lat", "39.91488908");
        bodys.put("lon", "116.40387397");
        //限行
//        String path = "/whapi/json/aliweather/limit";
//        bodys.put("token", "c712899b393c7b262dd7984f6eb52657");
        //15天预报
        String path = "/whapi/json/aliweather/forecast15days";
        bodys.put("token", "7538f7246218bdbf795b329ab09cc524");


        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtil.doPost(host, path, method, headers, querys, bodys);
            System.out.println(response.toString());
            //获取response的body
            System.out.println(EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String bytesToHexString(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            hexString.append(String.format("%02X", b));
        }
        return hexString.toString();
    }

    private String hexToString(String hexString) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < hexString.length(); i += 2) {
            String str = hexString.substring(i, i + 2);
            int decimalValue = Integer.parseInt(str, 16);
            stringBuilder.append((char) decimalValue);
        }
        return stringBuilder.toString();
    }

}
